package com.hexinfo.dmpro.data.transfer.common.common.session;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.hexinfo.dmpro.data.transfer.common.model.AgentInfo;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.atomic.AtomicInteger;

@Data
@Slf4j
@NoArgsConstructor
public class AgentSession {

    /**
     * 所属集群标识
     */
    private String clusterCode;

    /**
     * AGENT 唯一标识
     */
    private String agentKey;

    /**
     * AGENT 主机
     */
    private String agentHost;

    /**
     * AGENT 端口
     */
    private Integer agentPort;

    /**
     * AGENT 最大并发数
     */
    private Integer maxPoolSize;

    /**
     * AGENT 最新心跳时间
     */
    private String lastHeartbeatTime;

    /**
     * AGENT 当前并发数
     */
    private final AtomicInteger curConcurrentNum = new AtomicInteger(0);

    /**
     * 同步锁
     */
    private final byte[] curConcurrentNumSyn = {};

    public AgentSession(AgentInfo agentInfo) {
        this.agentKey = agentInfo.getAgentKey();
        this.agentHost = agentInfo.getAgentHost();
        this.agentPort = agentInfo.getAgentPort();
        this.maxPoolSize = agentInfo.getMaxPoolSize();
        this.lastHeartbeatTime = DateUtil.now();
        this.clusterCode = agentInfo.getClusterCode();
    }

    public boolean addExecuteTask() {
        synchronized (curConcurrentNumSyn) {
            if (this.curConcurrentNum.get() < this.maxPoolSize) {
                this.curConcurrentNum.addAndGet(1);
                return true;
            }
            return false;
        }
    }

    public boolean delExecuteTask() {
        synchronized (curConcurrentNumSyn) {
            if (this.curConcurrentNum.get() > 0) {
                this.curConcurrentNum.addAndGet(-1);
                return true;
            }
            return false;
        }
    }

    public boolean isAvailable() {
        return isAgentOnline() && this.curConcurrentNum.get() < this.maxPoolSize;
    }

    /*
     * @Method: isAgentOnline <br>
     * @Param: [] <br>
     * @Return: boolean <br>
     * @Description：最新心跳时间跟当前时间时间差在180秒内，则认为在线<br>
     * @Author： wz.li<br>
     * @Date： 2023/11/13 14:23 <br>
     * @Version： V2.0.2<br>
     */
    private boolean isAgentOnline() {
        return DateUtil.between(DateUtil.parse(lastHeartbeatTime), DateUtil.date(), DateUnit.SECOND) < 180;
    }

    public Integer getAgentIdleNum() {
        return this.maxPoolSize - this.curConcurrentNum.get();
    }
}
